import java.util.Scanner;

/**
 * UseHuffmanTranslator.java
 * Descripción: Permite al usuario ingresar una cadena para crear un código de Huffman
 *              y luego permite el ingreso de códigos para ser decodificados.
 * @author Oscar Castañeda 11086
 * @since 17/09/2012
 * @version 1.2
 */

public class UseHuffmanTranslator {
    
    private static Scanner usuario = new Scanner(System.in); //Para recibir las entradas del usuario.
    private static HuffmanTranslator huffmanTranslator = HuffmanTranslator.getInstance();  //Nos permite crear y traducir el código de Huffman.
    private static boolean firstUse = true; //Indica si es el primer uso del programa (equivalente a indicar si ya existe un Huffman tree (true) o no (false).
    
    /**
     * Ejecuta el programa.
     */
    public static void main (String args[]){
       menu();
    }

    /**
     * Imprime un menú para que el usuario genere un código de Huffman y pueda decodificar códigos a partir de él.
     */
    private static void menu(){
        boolean opcionValida; //Permite saber si el ingreso anterior es válido o no.
        String opcion = ""; //Opción ingresada por el usuario.
        do{
            //Se imprime el menú.
            System.out.println(":::Código de Huffman:::");
            System.out.println("1) Generar código de Huffman");
            System.out.println("2) Decodificar");
            System.out.println("3) Salir");
            opcionValida = false;
            //Y mientras la opción no sea válida
            while ((!opcionValida)){
                //Se obtiene el usuario una opción.
                System.out.println("Ingrese el número de su opción: ");
                opcion = usuario.nextLine();
                //Retirándole los espacios que pueda tener al principio o al final.
                opcion = opcion.trim();
                //Si es la opción para generar un código de Huffman.
                if (opcion.equals("1")){
                    //Se genera dicho código y se toma el ingreso como válido.
                    generateHuffman();
                    opcionValida = true;
                }else{
                    //Si es la opción para decodificar a partir del código recién generado.
                    if (opcion.equals("2")){
                        //Se decodifica, tomando el ingreso como válido.
                        decodeHuffman();
                        opcionValida = true;
                    }else{
                        //Si es la opción de salida
                        if(opcion.equals("3")){
                            //Se toma el ingreso como válido.
                           opcionValida = true;                           
                        }else{
                            //En cualquier otro caso, el ingreso es inválido y se le informa al usuario sobre esto.
                            System.out.println("Debe ingresar una opción válida (1, 2 o 3)");
                            opcionValida = false;
                        }
                    }
                }
            }
        }while(!opcion.equals("3"));
        //Se repetirá el menú mientras no se elija la opción de salida.
        System.out.println(">>>Programa terminado");
    }
    
    /**
     * Genera el código de Huffman para una cadena ingresada por el usuario.
     */
     private static void generateHuffman(){
        System.out.println(">>>Generar código de Huffman");
        String texto = ""; //Cadena semilla para el código.
        //Mientras la cadena ingresada sea vacía
        while (texto.equals("")){    
            //Se obtiene el ingreso del usuario
            System.out.println("Ingrese la cadena para generar el código de Huffman: ");
            texto = usuario.nextLine();
            //Y si dicho ingreso es una cadena vacía
            if (texto.equals("")){
                //Se indica el error y se pedirá otra cadena semilla.
                System.out.println("ERROR: Debe de ingresar al menos un caracter.");
            }
        }
        //Una vez obtenida la cadena, se hace reset al traductor de Huffman
        huffmanTranslator.reset();
        //Se genera el árbol de Huffman correspondiente y el diccionario.
        huffmanTranslator.generateHuffmanTree(texto);
        huffmanTranslator.generateDictionary();
        //Y se indica que ya se ha creado un árbol por primera vez.
        firstUse = false;
        //Se imprime en pantalla el código resultante.
        System.out.println("Código generado:");
        System.out.println(huffmanTranslator.getTable());
    }
     
     /**
      * Permite decodificar un código a partir del código de Huffman generado con 
      * anterioridad.
      */
    private static void decodeHuffman(){        
        //Si ya existe el código de Huffman
        if (!firstUse){
            System.out.println(">>>Decodificar con el código de Huffman generado");
            String encodedString = "";
            //Se recibe un ingreso del usuario, el cual se valida para que no sea una cadena vacía.
            while (encodedString.equals("")){    
               System.out.println("Ingrese el código a decodificar: ");
               encodedString = usuario.nextLine();
                if (encodedString.equals("")){
                    System.out.println("ERROR: Debe de ingresar al menos un caracter.");
                }
            }
            //Se decodifica y muestra en pantalla.
            System.out.println("Resultado de la decodificación:");
            System.out.println(huffmanTranslator.decode(encodedString));
        }else{
            //Si aún no existe un árbol de Huffman al seleccionar esta opción, se le indica al usuario.
            System.out.println("No ha creado un código de Huffman aún, así que se procederá a hacerlo ahora:");
            //Se genera dicho código
            generateHuffman();
            //Y luego se procede a decodificar la cadena ingresada.
            decodeHuffman();
        }
    }
}